{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ade7d4e6",
   "metadata": {},
   "source": [
    "# iFlow CLI Python SDK\n",
    "\n",
    "参考：[iFlow CLI Python SDK](https://platform.iflow.cn/cli/sdk/sdk-python)\n",
    "\n",
    "iFlow CLI SDK 是用于与 iFlow CLI 进行编程交互的 SDK。它通过代理通信协议（ACP）允许开发者构建具有对话、工具执行和任务规划能力的 AI 驱动应用程序。\n",
    "\n",
    "## 快速上手\n",
    "\n",
    "安装\n",
    "```\n",
    "pip install iflow-cli-sdk\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f7dbe6ad",
   "metadata": {},
   "source": [
    "SDK 会自动检测并启动 iFlow 进程，无需手动配置。SDK 自动处理：\n",
    "1. 检测 iFlow 是否已安装\n",
    "2. 启动 iFlow 进程（如果未运行）\n",
    "3. 查找可用端口并建立连接\n",
    "4. 退出时自动清理资源\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3602c4bc",
   "metadata": {},
   "source": [
    "### 简单示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "36cbfa4d",
   "metadata": {
    "tags": [
     "hide-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好！有什么我可以帮你的吗？\n"
     ]
    }
   ],
   "source": [
    "import logging\n",
    "# 将iflow_sdk模块的日志级别设置为WARNING或更高，避免打印信息过多\n",
    "logging.getLogger('iflow_sdk').setLevel(logging.WARNING)\n",
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, AssistantMessage, TaskFinishMessage\n",
    "\n",
    "async def main():\n",
    "    async with IFlowClient() as client:\n",
    "        await client.send_message(\"你好，iFlow！\")\n",
    "        \n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, AssistantMessage):\n",
    "                print(message.chunk.text, end=\"\\n\", flush=True)\n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                break\n",
    "\n",
    "await main()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6bdb59b",
   "metadata": {},
   "source": [
    "### 简单查询\n",
    "最简单的使用方式是通过 `query` 函数："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "e0b1fc15",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "法国的首都是巴黎。\n"
     ]
    }
   ],
   "source": [
    "from iflow_sdk import query\n",
    "\n",
    "response = await query(\"法国的首都是哪里？\")\n",
    "print(response) # 输出：法国的首都是巴黎。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bb366baa",
   "metadata": {},
   "source": [
    "## 核心概念\n",
    "\n",
    "### IFlowClient\n",
    "\n",
    "{class}`~iflow_sdk.IFlowClient` 是与 iFlow CLI 交互的主要接口，管理 WebSocket 连接的生命周期："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "12ca224f",
   "metadata": {},
   "outputs": [],
   "source": [
    "from iflow_sdk import IFlowClient, IFlowOptions\n",
    "\n",
    "# 使用默认配置（自动管理进程）\n",
    "async with IFlowClient() as client:\n",
    "    await client.send_message(\"你的问题\")\n",
    "\n",
    "    async for message in client.receive_messages():\n",
    "        # 处理消息\n",
    "        break"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "0a2762c8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 使用自定义配置\n",
    "options = IFlowOptions(\n",
    "    url=\"ws://localhost:8090/acp\", # WebSocket URL\n",
    "    auto_start_process=True, # 自动启动 iFlow\n",
    "    timeout=30.0 # 超时时间（秒）\n",
    ")\n",
    "async with IFlowClient(options) as client:\n",
    "    await client.send_message(\"你的问题\")\n",
    "    async for message in client.receive_messages():\n",
    "        # 处理消息\n",
    "        break"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "28370490",
   "metadata": {},
   "source": [
    "### 消息类型\n",
    "SDK 支持多种消息类型，对应 iFlow 协议的不同响应："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "53ed29fd",
   "metadata": {},
   "source": [
    "### AssistantMessage - AI 助手响应\n",
    "\n",
    "{class}`~iflow_sdk.AssistantMessage` 包含 `AgentInfo` 支持，可以获取代理的详细信息："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "997e1d08",
   "metadata": {
    "tags": [
     "hide-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python是一种高级编程语言，以其简洁易读的语法和强大的功能而闻名。它支持多种编程范式，包括面向对象、命令式、函数式和过程式编程。Python拥有丰富的标准库和第三方库，适用于Web开发、数据科学、人工智能、自动化脚本等多个领域。\n",
      "\n",
      "以下是Python的一些关键特性：\n",
      "\n",
      "1. **简单易学**：Python的语法设计强调代码的可读性，使得初学者能够快速上手。\n",
      "2. **跨平台**：Python可以在多种操作系统上运行，如Windows、macOS、Linux等。\n",
      "3. **解释型语言**：Python代码在运行时被逐行解释执行，无需预先编译成机器码。\n",
      "4. **动态类型系统**：变量不需要显式声明类型，Python会在运行时自动推断。\n",
      "5. **丰富的生态系统**：通过PyPI（Python Package Index）可以访问大量的开源库和工具。\n",
      "6. **广泛应用**：\n",
      "   - Web开发（如Django, Flask）\n",
      "   - 数据分析与科学计算（如NumPy, Pandas, Matplotlib）\n",
      "   - 机器学习与人工智能（如TensorFlow, PyTorch, Scikit-learn）\n",
      "   - 自动化运维与脚本编写\n",
      "   - 网络爬虫（如Scrapy, BeautifulSoup）\n",
      "\n",
      "如果你有特定的问题或想深入了解某个方面，请告诉我！\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, AssistantMessage, TaskFinishMessage, AgentInfo\n",
    "\n",
    "async def handle_assistant_message():\n",
    "    async with IFlowClient() as client:\n",
    "        await client.send_message(\"请介绍一下Python\")\n",
    "    \n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, AssistantMessage):\n",
    "                print(message.chunk.text, end=\"\\n\", flush=True)\n",
    "                # 访问代理信息（如果有）\n",
    "                if message.agent_info:\n",
    "                    print(f\"代理ID: {message.agent_info.agent_id}\")\n",
    "                    if message.agent_info.task_id:\n",
    "                        print(f\"任务ID: {message.agent_info.task_id}\")\n",
    "                    if message.agent_info.agent_index is not None:\n",
    "                        print(f\"代理索引: {message.agent_info.agent_index}\")\n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                break\n",
    "\n",
    "await handle_assistant_message()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b2dd790e",
   "metadata": {},
   "source": [
    "`AgentInfo` 使用示例"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "6c830ccc",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "代理ID: subagent-task-abc123-2-1735123456789\n",
      "任务ID: task-abc123\n",
      "代理索引: 2\n",
      "时间戳: 1735123456789\n"
     ]
    }
   ],
   "source": [
    "from iflow_sdk import AgentInfo\n",
    "\n",
    "# 从代理ID解析信息\n",
    "agent_id = \"subagent-task-abc123-2-1735123456789\"\n",
    "agent_info = AgentInfo.from_agent_id_only(agent_id)\n",
    "\n",
    "if agent_info:\n",
    "    print(f\"代理ID: {agent_info.agent_id}\")\n",
    "    print(f\"任务ID: {agent_info.task_id}\")\n",
    "    print(f\"代理索引: {agent_info.agent_index}\")\n",
    "    print(f\"时间戳: {agent_info.timestamp}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "05e4b55f",
   "metadata": {},
   "source": [
    "## `ToolCallMessage` - 工具调用\n",
    "工具调用消息现在也包含 `AgentInfo` 信息和工具名称："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "c76bebc0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "状态: ToolCallStatus.IN_PROGRESS\n",
      "工具名称: list_directory\n",
      "状态: ToolCallStatus.COMPLETED\n",
      "工具名称: list_directory\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, ToolCallMessage, ToolCallStatus, TaskFinishMessage\n",
    "\n",
    "async def handle_tool_calls():\n",
    "    async with IFlowClient() as client:\n",
    "        # 注意：这个示例演示如何查看工具调用消息\n",
    "        # iFlow 会要求提供完整路径和内容来创建文件\n",
    "        await client.send_message(\"列出当前目录的文件\")\n",
    "        \n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, ToolCallMessage):\n",
    "                print(f\"状态: {message.status}\")\n",
    "                \n",
    "                # 新增：工具名称\n",
    "                if message.tool_name:\n",
    "                    print(f\"工具名称: {message.tool_name}\")\n",
    "                \n",
    "                # 访问代理信息\n",
    "                if message.agent_info:\n",
    "                    print(f\"代理ID: {message.agent_info.agent_id}\")\n",
    "                    \n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                break\n",
    "\n",
    "await handle_tool_calls()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f12cb4c0",
   "metadata": {},
   "source": [
    "### PlanMessage - 任务计划"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3b01e6d6",
   "metadata": {
    "tags": [
     "hide-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "执行计划：\n",
      "⏳ [low] 创建项目根目录\n",
      "⏳ [low] 创建项目子目录（如src, tests, docs等）\n",
      "⏳ [low] 创建必要的项目文件（如README.md, pyproject.toml等）\n",
      "⏳ [low] 创建示例源代码文件\n",
      "⏳ [low] 创建示例测试文件\n",
      "执行计划：\n",
      "✅ [low] 创建项目根目录\n",
      "✅ [low] 创建项目子目录（如src, tests, docs等）\n",
      "⏳ [low] 创建必要的项目文件（如README.md, pyproject.toml等）\n",
      "⏳ [low] 创建示例源代码文件\n",
      "⏳ [low] 创建示例测试文件\n",
      "执行计划：\n",
      "✅ [low] 创建项目根目录\n",
      "✅ [low] 创建项目子目录（如src, tests, docs等）\n",
      "✅ [low] 创建必要的项目文件（如README.md, pyproject.toml等）\n",
      "⏳ [low] 创建示例源代码文件\n",
      "⏳ [low] 创建示例测试文件\n",
      "执行计划：\n",
      "✅ [low] 创建项目根目录\n",
      "✅ [low] 创建项目子目录（如src, tests, docs等）\n",
      "✅ [low] 创建必要的项目文件（如README.md, pyproject.toml等）\n",
      "✅ [low] 创建示例源代码文件\n",
      "⏳ [low] 创建示例测试文件\n",
      "执行计划：\n",
      "✅ [low] 创建项目根目录\n",
      "✅ [low] 创建项目子目录（如src, tests, docs等）\n",
      "✅ [low] 创建必要的项目文件（如README.md, pyproject.toml等）\n",
      "✅ [low] 创建示例源代码文件\n",
      "✅ [low] 创建示例测试文件\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, PlanMessage, TaskFinishMessage\n",
    "\n",
    "async def show_plan():\n",
    "    async with IFlowClient() as client:\n",
    "        await client.send_message(\"帮我创建一个Python项目结构\")\n",
    "        \n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, PlanMessage):\n",
    "                print(\"执行计划：\")\n",
    "                for entry in message.entries:\n",
    "                    status_icon = \"✅\" if entry.status == \"completed\" else \"⏳\"\n",
    "                    print(f\"{status_icon} [{entry.priority}] {entry.content}\")\n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                break\n",
    "\n",
    "await show_plan()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c39474ef",
   "metadata": {},
   "source": [
    "### TaskFinishMessage - 任务完成"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a87aea50",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n",
      "任务正常完成\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, AssistantMessage, TaskFinishMessage, StopReason\n",
    "\n",
    "async def check_completion():\n",
    "    async with IFlowClient() as client:\n",
    "        await client.send_message(\"计算 1+1\")\n",
    "        \n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, AssistantMessage):\n",
    "                print(message.chunk.text, end=\"\", flush=True)\n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                print()  # 换行\n",
    "                if message.stop_reason == StopReason.END_TURN:\n",
    "                    print(\"任务正常完成\")\n",
    "                elif message.stop_reason == StopReason.MAX_TOKENS:\n",
    "                    print(\"达到最大令牌限制\")\n",
    "                break  # TaskFinishMessage 表示对话结束\n",
    "await check_completion()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a6ed5b7b",
   "metadata": {},
   "source": [
    "## 常见用例\n",
    "\n",
    "### 交互式聊天机器人"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "622c42f1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "iFlow 聊天机器人 (输入 'quit' 退出)\n",
      "--------------------------------------------------\n",
      "iFlow: Hello! It seems like you've sent a message with just \"qq\". Could you please provide more context or let me know what you'd like help with? I'm here to assist you with any questions or tasks you might have.\n",
      "再见！\n"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, AssistantMessage, TaskFinishMessage\n",
    "\n",
    "async def chatbot():\n",
    "    print(\"iFlow 聊天机器人 (输入 'quit' 退出)\")\n",
    "    print(\"-\" * 50)\n",
    "    \n",
    "    async with IFlowClient() as client:\n",
    "        while True:\n",
    "            user_input = input(\"\\n你: \")\n",
    "            \n",
    "            if user_input.lower() in ['quit', 'exit', 'q']:\n",
    "                print(\"再见！\")\n",
    "                break\n",
    "            \n",
    "            await client.send_message(user_input)\n",
    "            \n",
    "            print(\"iFlow: \", end=\"\", flush=True)\n",
    "            async for message in client.receive_messages():\n",
    "                if isinstance(message, AssistantMessage):\n",
    "                    print(message.chunk.text, end=\"\", flush=True)\n",
    "                elif isinstance(message, TaskFinishMessage):\n",
    "                    print()  # 换行\n",
    "                    break\n",
    "\n",
    "await chatbot()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2974e15",
   "metadata": {},
   "source": [
    "### 流式响应处理"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "fd35cb69",
   "metadata": {
    "tags": [
     "hide-output"
    ]
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "升华现象是指物质从固态直接转变为气态的过程，而不经过液态阶段。这一过程是物理变化，通常发生在特定的温度和压力条件下。\n",
      "\n",
      "### 关键特点：\n",
      "1. **直接转变**：固态物质直接变为气态，跳过液态。\n",
      "2. **吸热过程**：升华需要吸收热量，称为升华热。\n",
      "3. **可逆性**：气态物质也可以直接转变为固态，称为凝华。\n",
      "\n",
      "### 常见例子：\n",
      "- **干冰（固态二氧化碳）**：在常温下直接升华为气体，用于制冷和舞台效果。\n",
      "- **樟脑丸**：在空气中逐渐升华，释放气味。\n",
      "- **碘晶体**：加热时直接升华为紫色气体。\n",
      "\n",
      "### 应用领域：\n",
      "- **冷冻干燥**：用于保存食品和药品，通过升华去除水分。\n",
      "- **化学实验**：分离和纯化某些固体物质。\n",
      "- **日常应用**：如空气清新剂、防虫剂等。\n",
      "\n",
      "升华现象在日常生活和工业中都有广泛应用，理解其原理有助于更好地利用这一特性。\n"
     ]
    }
   ],
   "source": [
    "from iflow_sdk import query_stream\n",
    "import asyncio\n",
    "\n",
    "async def stream_example():\n",
    "    prompt = \"解释一下什么是升华现象\"\n",
    "    \n",
    "    # query_stream 返回文本块的异步生成器\n",
    "    async for chunk in query_stream(prompt):\n",
    "        print(chunk, end=\"\", flush=True)\n",
    "    print()  # 最后换行\n",
    "\n",
    "await stream_example()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6efff336",
   "metadata": {},
   "source": [
    "## 高级配置\n",
    "### 手动进程管理\n",
    "如果需要手动管理 iFlow 进程："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4497d522",
   "metadata": {},
   "source": [
    "```python\n",
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, IFlowOptions, AssistantMessage, TaskFinishMessage\n",
    "\n",
    "async def manual_process_example():\n",
    "    # 禁用自动进程管理\n",
    "    options = IFlowOptions(\n",
    "        auto_start_process=False,\n",
    "        url=\"ws://localhost:8090/acp\"  # 连接到已存在的 iFlow\n",
    "    )\n",
    "    \n",
    "    async with IFlowClient(options) as client:\n",
    "        await client.send_message(\"你的问题\")\n",
    "        async for message in client.receive_messages():\n",
    "            if isinstance(message, AssistantMessage):\n",
    "                print(message.chunk.text, end=\"\", flush=True)\n",
    "            elif isinstance(message, TaskFinishMessage):\n",
    "                break\n",
    "\n",
    "if __name__ == \"__main__\":\n",
    "    asyncio.run(manual_process_example())\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a0208c4",
   "metadata": {},
   "source": [
    "````{tip}\n",
    "注意 手动模式需要您单独启动 iFlow：\n",
    "```bash\n",
    "iflow --experimental-acp --port 8090\n",
    "```\n",
    "````\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f17948f9",
   "metadata": {},
   "source": [
    "### 错误处理\n",
    "SDK 提供了详细的错误处理机制："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "cf1d612b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "你好！看起来你可能想进行一些测试。你具体想测试什么呢？是关于代码、功能还是其他方面？请提供更多细节，我会尽力帮助你。"
     ]
    }
   ],
   "source": [
    "import asyncio\n",
    "from iflow_sdk import IFlowClient, ConnectionError, TimeoutError, AssistantMessage, TaskFinishMessage\n",
    "\n",
    "async def error_handling_example():\n",
    "    try:\n",
    "        async with IFlowClient() as client:\n",
    "            await client.send_message(\"测试\")\n",
    "            async for message in client.receive_messages():\n",
    "                if isinstance(message, AssistantMessage):\n",
    "                    print(message.chunk.text, end=\"\", flush=True)\n",
    "                elif isinstance(message, TaskFinishMessage):\n",
    "                    break\n",
    "    except ConnectionError as e:\n",
    "        print(f\"连接错误: {e}\")\n",
    "    except TimeoutError as e:\n",
    "        print(f\"超时错误: {e}\")\n",
    "    except Exception as e:\n",
    "        print(f\"未知错误: {e}\")\n",
    "\n",
    "await error_handling_example()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38cd70c4",
   "metadata": {},
   "source": [
    "### 同步调用\n",
    "对于需要同步调用的场景：\n",
    "\n",
    "```python\n",
    "from iflow_sdk import query_sync, IFlowOptions\n",
    "\n",
    "# 同步调用，带超时控制\n",
    "options = IFlowOptions(timeout=30.0)\n",
    "response = query_sync(\"你的问题\", options=options)\n",
    "print(response)\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "07d63897",
   "metadata": {},
   "source": [
    "### 日志调试\n",
    "启用详细日志以便调试："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "6010d8cf",
   "metadata": {},
   "outputs": [],
   "source": [
    "import logging\n",
    "from iflow_sdk import IFlowClient, IFlowOptions\n",
    "\n",
    "# 设置日志级别\n",
    "logging.basicConfig(level=logging.DEBUG)\n",
    "\n",
    "options = IFlowOptions(log_level=\"DEBUG\")\n",
    "client = IFlowClient(options)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "558ea820",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "py313",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.13.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
